/*
 * Copyright 2010 Kevin L'Huillier <klhuillier@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.lhuillier.pwsafe.model;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;


public class Record {
    private final UUID uuid;
    private String group;
    private String title;
    private String username;
    private String notes;
    private String password;
    private Date creationTime;
    private Date passwordModifyTime;
    private Date lastAccessTime;
    private Date passwordExpiryTime;
    private Date lastModifyTime;
    private String url;
    private String autotype;
    private PasswordHistory passwordHistory;
    private RecordPwPolicy passwordPolicy;
    // 0-3650 (2 bytes; 0=unset)
    private Short expiryInterval;
    private String runCommand;
    private DoubleClickAction doubleClickAction;
    private String emailAddress;
    private HashMap<Byte, RawField> unknownFields =
            new HashMap<Byte, RawField>();

    public Record() {
        this(UUID.randomUUID());
    }

    public Record(UUID uuid) {
        if (uuid == null) {
            throw new NullPointerException("uuid");
        }
        this.uuid = uuid;
    }

    public UUID getUuid() {
        return uuid;
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getCreationTime() {
        return creationTime;
    }

    public void setCreationTime(Date creationTime) {
        this.creationTime = creationTime;
    }

    public Date getPasswordModifyTime() {
        return passwordModifyTime;
    }

    public void setPasswordModifyTime(Date passwordModifyTime) {
        this.passwordModifyTime = passwordModifyTime;
    }

    public Date getLastAccessTime() {
        return lastAccessTime;
    }

    public void setLastAccessTime(Date lastAccessTime) {
        this.lastAccessTime = lastAccessTime;
    }

    public Date getPasswordExpiryTime() {
        return passwordExpiryTime;
    }

    public void setPasswordExpiryTime(Date passwordExpiryTime) {
        this.passwordExpiryTime = passwordExpiryTime;
    }

    public Date getLastModifyTime() {
        return lastModifyTime;
    }

    public void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getAutotype() {
        return autotype;
    }

    public void setAutotype(String autotype) {
        this.autotype = autotype;
    }

    public PasswordHistory getPasswordHistory() {
        return passwordHistory;
    }

    // TODO: Remove this; make history 1:1 with a Record
    public void setPasswordHistory(PasswordHistory passwordHistory) {
        this.passwordHistory = passwordHistory;
    }

    public RecordPwPolicy getPasswordPolicy() {
        return passwordPolicy;
    }

    // TODO: Remove this; make policy 1:1 with a Record
    public void setPasswordPolicy(RecordPwPolicy passwordPolicy) {
        this.passwordPolicy = passwordPolicy;
    }

    /**
     * Expiration interval in days. Valid values are 0-3650, where null or
     * 0 means it does not expire.
     */
    public Short getExpiryInterval() {
        return expiryInterval;
    }

    /**
     * Expiration interval in days. Valid values are 0-3650, where null or
     * 0 means it does not expire.
     */
    public void setExpiryInterval(Short expiryInterval) {
        this.expiryInterval = expiryInterval;
    }

    public String getRunCommand() {
        return runCommand;
    }

    public void setRunCommand(String runCommand) {
        this.runCommand = runCommand;
    }

    public DoubleClickAction getDoubleClickAction() {
        return doubleClickAction;
    }

    public void setDoubleClickAction(DoubleClickAction doubleClickAction) {
        this.doubleClickAction = doubleClickAction;
    }

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    /**
     * Returns all fields which were added as unknown fields.
     * <p>
     * The returned list is a copy of the values. Modifying this copy will
     * not affect the Header instance.
     *
     * @return a list of unknown fields
     */
    public List<RawField> getUnknownFields() {
        ArrayList<RawField> result =
                new ArrayList<RawField>(unknownFields.values());
        Collections.sort(result, new FieldIdComparator());
        return result;
    }

    /**
     * If field is null, this removes any value for the given typeId, otherwise
     * it will replace any existing value or add a new value for the typeId.
     */
    public void setUnknownField(Byte typeId, RawField field) {
        if (field == null) {
            unknownFields.remove(typeId);
        } else {
            unknownFields.put(typeId, field);
        }
    }

    public RawField getUnknownField(byte typeId) {
        return unknownFields.get(typeId);
    }

    @Override
    public int hashCode() {
        return uuid.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        } else if (obj == this) {
            return true;
        } else if (!obj.getClass().equals(getClass())) {
            return false;
        }
        return uuid.equals(((Record) obj).uuid);
    }
}
